package com.liang.blog.system.service.impl;

import com.alibaba.excel.EasyExcel;
import com.liang.blog.model.BlogDict;
import com.liang.blog.system.listener.DictListener;
import com.liang.blog.system.mapper.BlogDictMapper;
import com.liang.blog.system.service.BlogDictService;
import com.liang.blog.vo.cmn.DictEeVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author：YanWenLiang
 * @Date:2023-08-30-19:54
 */
@Service
public class BlogDictServiceImpl implements BlogDictService {

    @Autowired
    private BlogDictMapper blogDictMapper;

    /**
     * 根据编码获取字典信息
     * @param code
     * @return
     */
    @Override
    public List<BlogDict> getBlogDictByCode(String code) {
        return blogDictMapper.getBlogDictByCode(code);
    }

    /**
     * 通过父 id 查询字典信息
     *
     * @param id
     * @return
     */
    @Override
    public List<BlogDict> findChildData(Long id) {
        List<BlogDict> childData = blogDictMapper.findChildData(id);
        List<Long> ids = childData.stream().map(BlogDict::getId).collect(Collectors.toList());

        Map<Long, Boolean> childrenMap = this.isChildrenList(ids);
        childData.forEach(dict -> dict.setHasChildren(childrenMap.get(dict.getId())));
        return childData;
    }


    /**
     * 判断是否有子节点
     *
     * @param ids
     * @return
     */
    public Map<Long, Boolean> isChildrenList(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return Collections.emptyMap();
        }

        List<Long> dictParentIds = blogDictMapper.getDictParentIds(ids);
        // 通过 stream 流将 List<Obj> 转成 List<Long>
        List<Long> list = dictParentIds.stream()
                .map(obj -> Long.parseLong(obj.toString()))
                .collect(Collectors.toList());
        // 用于存储节点信息 ==》 {id ==> true/false}
        Map<Long, Boolean> childrenMap = new HashMap<>();

        // 将查询出来的子节点的父 id 设置为 true
        list.forEach(parentId -> childrenMap.put(parentId, Boolean.TRUE));

        // 将父节点的 id 与子节点的父 id 匹配，不存在 map 中，说明通过该父节点的 id 没有查到子节点
        ids.forEach(id -> {
            if (!childrenMap.containsKey(id)) {
                childrenMap.put(id, Boolean.FALSE);
            }
        });
        return childrenMap;
    }

    /**
     * 导出字典表
     * @param response
     */
    @Override
    public void exportDict(HttpServletResponse response) {
        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("数据字典", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            // 查询数据库获取字典信息
            List<BlogDict> dictList = blogDictMapper.getDictAll();
            // dict ==> dictVO
            List<DictEeVo> dictEeVos = new ArrayList<>();
            dictList.forEach(dict -> {
                DictEeVo dictEeVo = new DictEeVo();
                BeanUtils.copyProperties(dict, dictEeVo);
                dictEeVos.add(dictEeVo);
            });

            // 调用excel写方法
            EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("数据字典")
                    .doWrite(dictEeVos);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 导入字典表
     * @param file
     */
    @Override
    public void importData(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(), DictEeVo.class, new DictListener(blogDictMapper)).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 通过 code 和 value 获取 字典信息
     * @param dictCode
     * @param value
     * @return
     */
    @Override
    public String getDictName(String dictCode, String value) {
        return blogDictMapper.getDictName(dictCode, value);
    }

}
